package com.ssy.lingxi.platform.template.service.serviceimpl.web;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.constant.template.MemberShopEntity;
import com.ssy.lingxi.common.constant.template.PageTemplateTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberInnerControllerFeign;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberLevelRightCreditControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignIdVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberShopFeignVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignLrcVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignRegisterQueryVO;
import com.ssy.lingxi.platform.manage.api.feign.inner.AreaControllerFeign;
import com.ssy.lingxi.platform.template.service.constant.CommonBooleanEnum;
import com.ssy.lingxi.platform.template.service.constant.PageTemplateEnvironmentEnum;
import com.ssy.lingxi.platform.template.service.constant.SeoDoorTypeEnum;
import com.ssy.lingxi.platform.template.service.constant.SeoTypeEnum;
import com.ssy.lingxi.platform.template.service.entity.adorn.PageTemplate;
import com.ssy.lingxi.platform.template.service.entity.collect.MemberShopCollect;
import com.ssy.lingxi.platform.template.service.entity.door.MemberShop;
import com.ssy.lingxi.platform.template.service.entity.door.QMemberShop;
import com.ssy.lingxi.platform.template.service.entity.door.Seo;
import com.ssy.lingxi.platform.template.service.model.bo.AreaBO;
import com.ssy.lingxi.platform.template.service.model.dto.common.CollectDTO;
import com.ssy.lingxi.platform.template.service.model.dto.common.IdDTO;
import com.ssy.lingxi.platform.template.service.model.dto.common.IdListDTO;
import com.ssy.lingxi.platform.template.service.model.dto.common.MemberIdRoleIdShopIdDTO;
import com.ssy.lingxi.platform.template.service.model.dto.web.SaveShopDTO;
import com.ssy.lingxi.platform.template.service.model.qo.CommonIdListPageQO;
import com.ssy.lingxi.platform.template.service.model.qo.MemberShopInGoodsListAdornQO;
import com.ssy.lingxi.platform.template.service.model.qo.MemberShopQO;
import com.ssy.lingxi.platform.template.service.model.vo.web.*;
import com.ssy.lingxi.platform.template.service.repository.MemberShopCollectRepository;
import com.ssy.lingxi.platform.template.service.repository.MemberShopRepository;
import com.ssy.lingxi.platform.template.service.repository.PageTemplateRepository;
import com.ssy.lingxi.platform.template.service.repository.SeoRepository;
import com.ssy.lingxi.platform.template.service.service.web.MemberShopWebService;
import com.ssy.lingxi.product.api.feign.ICommodityFeign;
import com.ssy.lingxi.product.api.model.request.MemberRequest;
import com.ssy.lingxi.product.api.model.response.store.StoreResponse;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.enums.ShopOperateTypeEnum;
import com.ssy.lingxi.report.api.feign.ReportControllerFeign;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.search.api.feign.ITemplateFeign;
import com.ssy.lingxi.search.api.model.request.StoreIdListRequest;
import com.ssy.lingxi.search.api.model.request.TemplateCommoditySearchRequest;
import com.ssy.lingxi.search.api.model.response.CommoditySearchResponse;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * @author fhj
 * @version 2.0.0
 * @menu web - 会员店铺门户 - 业务实现层
 * @date 2020/12/09
 */
@Slf4j
@Service
public class MemberShopWebServiceImpl implements MemberShopWebService {

    @Resource
    private PageTemplateRepository pageTemplateRepository;
    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private MemberShopRepository memberShopRepository;
    @Resource
    private MemberLevelRightCreditControllerFeign memberLevelRightCreditControllerFeign;
    @Resource
    private ReportControllerFeign reportController;
    @Resource
    private MemberShopCollectRepository memberShopCollectRepository;
    @Resource
    private ICommodityFeign commodityFeign;
    @Resource
    private MemberInnerControllerFeign memberInnerControllerFeign;
    @Resource
    private AreaControllerFeign areaControllerFeign;
    @Resource
    private ITemplateFeign templateFeign;
    @Resource
    private SeoRepository seoRepository;
    @Resource
    private IRedisStringUtils redisStringUtils;

    @Override
    @Transactional
    @ApiOperation(value = "保存当前登录会员的店铺门户")
    public Wrapper<Void> saveCurrMemberShop(SaveShopDTO dto, UserLoginCacheDTO user) {
        //校验（只有是服务提供者且企业类型是企业会员或个人会员才能创建店铺, 支持一个会员多个店铺, 因为一个会员可以有多个服务提供角色）
        if (!user.getMemberRoleType().equals(RoleTypeEnum.SERVICE_PROVIDER.getCode())) {
            return Wrapper.fail("角色类型不是服务提供者, 不能创建店铺");
        }
        if (!(user.getMemberType().equals(MemberTypeEnum.MERCHANT.getCode()) || user.getMemberType().equals(MemberTypeEnum.MERCHANT_PERSONAL.getCode()))) {
            return Wrapper.fail("会员类型不是企业会员或个人会员, 不能创建店铺");
        }

        //默认省、市编码都为0（所有/所有）
        List<String> provinceCodes = Stream.of("0").collect(toList());
        List<String> cityCodes = Stream.of("0").collect(toList());
        if (dto.getMemberShopAreas().stream().noneMatch(a -> a.getProvinceCode().equals("0"))) {
            provinceCodes = dto.getMemberShopAreas().stream().map(AreaBO::getProvinceCode).collect(Collectors.toList());
            cityCodes = dto.getMemberShopAreas().stream().filter(a -> !a.getCityCode().equals("0")).map(AreaBO::getCityCode).collect(Collectors.toList());

            List<String> feignCodes = dto.getMemberShopAreas().stream().filter(a -> a.getCityCode().equals("0")).map(AreaBO::getProvinceCode).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(feignCodes)) {
                Wrapper<List<String>> cityCodesWrapper = areaControllerFeign.findCityCodeByProvinceCode(feignCodes);
                if (cityCodesWrapper.getCode() == ResponseCode.SUCCESS.getCode() && CollectionUtil.isNotEmpty(cityCodesWrapper.getData())) {
                    cityCodes.addAll(cityCodesWrapper.getData());
                }
            }
        }

        //调用会员服务 -> 根据会员ID和角色ID获取平台会员的等级、注册年数、信用积分
        MemberFeignVO memberFeignVO = new MemberFeignVO();
        memberFeignVO.setMemberId(user.getMemberId());
        memberFeignVO.setRoleId(user.getMemberRoleId());
        Wrapper<MemberFeignLrcVO> platformMemberLrcWrapper = memberLevelRightCreditControllerFeign.getPlatformMemberLrc(memberFeignVO);
        if (platformMemberLrcWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("调用会员服务失败：{}", platformMemberLrcWrapper.getMessage());
            return Wrapper.fail(ResponseCode.SERVICE_MERCHANT_MEMBER_ERROR);
        }
        //调用会员服务 -> 根据会员Id查询会员注册信息
        MemberFeignIdVO memberFeignIdVO = new MemberFeignIdVO();
        memberFeignIdVO.setMemberId(user.getMemberId());
        Wrapper<MemberFeignRegisterQueryVO> memberRegisterInfoWrapper = memberInnerControllerFeign.getMemberRegisterInfo(memberFeignIdVO);
        if (memberRegisterInfoWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("调用会员服务失败：{}", memberRegisterInfoWrapper.getMessage());
        }

        //根据会员ID和角色ID获取会员店铺。flag是判断需不需要调用报表服务的标识（为true说明是创建店铺，false是更新店铺）
        MemberShop memberShop = memberShopRepository.findByMemberIdAndRoleId(user.getMemberId(), user.getMemberRoleId());
        boolean flag = memberShop == null;

        //如果会员店铺不为空则是更新店铺，否则就是初始化店铺
        memberShop = memberShop != null ? memberShop : new MemberShop();
        memberShop.setMemberId(user.getMemberId());
        memberShop.setRoleId(user.getMemberRoleId());
        memberShop.setName(dto.getName());
        memberShop.setMemberShopAreas(dto.getMemberShopAreas());
        memberShop.setLogo(dto.getLogo());
        memberShop.setDescribe(dto.getDescribe());
        memberShop.setWorkshopPics(dto.getWorkshopPics());
        memberShop.setHonorPics(dto.getHonorPics());
        memberShop.setAlbumName(dto.getAlbumName());
        memberShop.setAlbumUrl(dto.getAlbumUrl());
        memberShop.setPromotionPic(dto.getPromotionPic());
        memberShop.setPhone(dto.getPhone());
        memberShop.setAddress(dto.getAddress());
        memberShop.setLng(dto.getLng());
        memberShop.setLat(dto.getLat());
        memberShop.setAreas(dto.getMemberShopAreas().stream().map(a -> a.getProvince() + "/" + a.getCity()).collect(Collectors.joining("，")));
        memberShop.setProvincesCodeList(String.join("，", provinceCodes));
        memberShop.setCityCodeList(String.join("，", cityCodes));
        memberShop.setMemberName(user.getCompany());
        memberShop.setLevelTag(platformMemberLrcWrapper.getData().getLevelTag());
        memberShop.setRegisterYears(platformMemberLrcWrapper.getData().getRegisterYears());
        memberShop.setCreditPoint(platformMemberLrcWrapper.getData().getCreditPoint());
        memberShop.setRegisteredCapital(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getRegisteredCapital() : null);
        memberShop.setEstablishmentDate(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getEstablishmentDate() : null);
        memberShop.setBusinessLicence(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getBusinessLicence() : null);
        memberShop.setRegisterArea(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getRegisterArea() : null);
        memberShop.setRegisterAddress(memberRegisterInfoWrapper.getData() != null ? memberRegisterInfoWrapper.getData().getRegisterAddress() : null);
        memberShopRepository.saveAndFlush(memberShop);

        //标识为true则是创建店铺，需要统计创建店铺数量。调用报表服务 -> 新增操作通知（如果调用过程出现异常, 无需回滚, 直接catch打印日志正常返回。）
        try {
            if (flag) {
                OperateNoticeVO noticeVO = new OperateNoticeVO();
                noticeVO.setMemberId(user.getMemberId());
                noticeVO.setRoleId(user.getMemberRoleId());
                noticeVO.setDataSource(OperateDataSourceEnum.SHOP.getCode());
                noticeVO.setIncreaseOperateType(ShopOperateTypeEnum.ADD.getCode());
                noticeVO.setIncreaseCount(1L);
                reportController.addOperateNotice(noticeVO);
            }
        } catch (Exception e) {
            log.info("调用报表服务新增操作通知接口失败：{}", e.getMessage());
        }

        //将会员店铺缓存到redis
        redisStringUtils.hSet(Constants.REDIS_KEY_MEMBER_SHOP, String.valueOf(memberShop.getId()), JSONUtil.toJsonStr(BeanUtil.copyProperties(memberShop, MemberShopEntity.class)), Constants.REDIS_TEMPLATE_INDEX);

        //调用会员服务 - 店铺模板服务 - 新增或更新店铺
        MemberShopFeignVO memberShopFeignVO = new MemberShopFeignVO();
        memberShopFeignVO.setMemberId(memberShop.getMemberId());
        memberShopFeignVO.setRoleId(memberShop.getRoleId());
        memberShopFeignVO.setName(memberShop.getName());
        memberShopFeignVO.setLogo(memberShop.getLogo());
        Wrapper<Void> memberWrapper = memberInnerControllerFeign.insertOrUpdateMemberShop(memberShopFeignVO);
        if (memberWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员服务调用失败，没将logo、名称同步到会员服务过去，错误原因：{}", memberWrapper.getMessage());
        }

        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "获取当前登录会员的店铺门户")
    public Wrapper<MemberShop> findCurrMemberShop(UserLoginCacheDTO user) {
        return Wrapper.success(memberShopRepository.findByMemberIdAndRoleId(user.getMemberId(), user.getMemberRoleId()));
    }

    @Override
    @ApiOperation(value = "店铺门户主页")
    public Wrapper<MemberShopMainVO> memberShopMain(MemberIdRoleIdShopIdDTO dto, UserLoginCacheDTO user) {
        //根据会员ID和角色ID获取店铺
        MemberShop memberShop = memberShopRepository.findByMemberIdAndRoleId(dto.getMemberId(), dto.getRoleId());
        if (memberShop == null) {
            return Wrapper.fail(ResponseCode.PT_NOT_FOUND_MEMBER_SHOP);
        }

        //拷贝
        MemberShopMainVO memberShopMainVO = new MemberShopMainVO();
        BeanUtils.copyProperties(memberShop, memberShopMainVO);

        //封装正在使用的店铺模板
        List<PageTemplate> pageTemplateList = pageTemplateRepository.findByEnvironmentAndTypeAndStatusAndShelfAndShopId(
                PageTemplateEnvironmentEnum.WEB.getCode(),
                PageTemplateTypeEnum.SHOP.getCode(),
                CommonBooleanEnum.YES.getCode(),
                CommonBooleanEnum.YES.getCode(),
                dto.getShopId()
        );
        if (CollectionUtil.isNotEmpty(pageTemplateList)) {
            pageTemplateList = pageTemplateList.stream().filter(a ->
                    CollectionUtil.isNotEmpty(a.getUseShopTemplate()) &&
                            a.getUseShopTemplate().stream().anyMatch(b ->
                                    b.getMemberId().equals(memberShop.getMemberId()) && b.getRoleId().equals(memberShop.getRoleId())
                            )
            ).collect(Collectors.toList());

            if (CollectionUtil.isNotEmpty(pageTemplateList)) {
                if (pageTemplateList.size() > 1) {
                    log.error("正在使用的店铺模板出现多个【检查原因】");
                }
                PageTemplate pageTemplate = pageTemplateList.get(0);
                memberShopMainVO.setTemplateId(pageTemplate.getId());
                memberShopMainVO.setFileName(pageTemplate.getFileName());
                //设置用户自己的mro是否开启
                memberShopMainVO.setOpenMro(pageTemplate.getUseShopTemplate().stream().filter(e -> dto.getMemberId().equals(e.getMemberId()) && dto.getRoleId().equals(e.getRoleId())).collect(toList()).get(0).getOpenMro());
            }
        }

        //收藏状态
        if (user != null) {
            memberShopMainVO.setCollectStatus(memberShopCollectRepository.existsByShopIdAndMemberIdAndUserId(memberShop.getId(), user.getMemberId(), user.getUserId()));
        }

        //调用商品服务 -> 根据会员ID和角色ID集合获取店铺的主营分类
        MemberRequest memberRequest = new MemberRequest();
        memberRequest.setMemberId(memberShopMainVO.getMemberId());
        memberRequest.setMemberRoleId(memberShopMainVO.getRoleId());
        Map<String, StoreResponse> map = commodityFeign.getCommodityAndCategoryByMemberIdAndMemberRoleId(
                Stream.of(memberRequest).collect(toList())
        );
        if (CollectionUtil.isNotEmpty(map) && map.get(memberShopMainVO.getMemberId() + "-" + memberShopMainVO.getRoleId()) != null) {
            memberShopMainVO.setCustomerCategoryName(map.get(memberShopMainVO.getMemberId() + "-" + memberShopMainVO.getRoleId()).getCustomerCategoryName());
        }

        //获取店铺SEO
        List<Seo> seoList = seoRepository.findAllByDoorTypeAndDoorIdAndStatus(
                SeoDoorTypeEnum.SHOP.getCode(),
                memberShop.getId(),
                CommonBooleanEnum.YES.getCode()
        );
        //封装店铺SEO(首页、关于我们)
        if (CollectionUtil.isNotEmpty(seoList)) {
            Seo homePage = seoList.stream().filter(a -> a.getType().equals(SeoTypeEnum.HOME_PAGE.getCode())).findFirst().orElse(null);
            Seo aboutUs = seoList.stream().filter(a -> a.getType().equals(SeoTypeEnum.ABOUT_US.getCode())).findFirst().orElse(null);
            memberShopMainVO.setHomePage(homePage);
            memberShopMainVO.setAboutUs(aboutUs);
        }

        return Wrapper.success(memberShopMainVO);
    }

    @Override
    @ApiOperation(value = "店铺门户列表")
    public Wrapper<PageData<MemberShopListVO>> memberShopList(MemberShopQO qo, Long shopId) {
        //查询表实体 - 店铺门户
        QMemberShop memberShop = QMemberShop.memberShop;

        //查询条件构造 - 搜索条件
        BooleanBuilder predicates = new BooleanBuilder();

        //搜索条件 - 平台品类ID。调用商品服务 -> 通过平台品类id查询会员ID集合，根据会员ID过滤店铺门户。
        if (qo.getCategoryId() != null) {
            Wrapper<List<Long>> getMemberIdListWrapper = commodityFeign.getMemberIdList(qo.getCategoryId());
            if (getMemberIdListWrapper.getCode() == ResponseCode.SUCCESS.getCode()) {
                if (CollectionUtil.isNotEmpty(getMemberIdListWrapper.getData())) {
                    predicates.and(memberShop.memberId.in(getMemberIdListWrapper.getData()));
                } else {
                    return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
                }
            } else {
                log.info("请求商品服务失败:{}", getMemberIdListWrapper.getMessage());
            }
        }
        //搜索条件 - 会员名称。
        if (StringUtils.isNotBlank(qo.getMemberName())) {
            predicates.and(memberShop.memberName.like("%" + qo.getMemberName() + "%"));
        }
        //搜索条件 - 省编码。
        if (StringUtils.isNotBlank(qo.getProvinceCode())) {
            predicates.and(
                    memberShop.provincesCodeList.like("%" + qo.getProvinceCode() + "%")
                            .or(memberShop.provincesCodeList.eq("0"))
            );
        }
        //搜索条件 - 市编码。
        if (StringUtils.isNotBlank(qo.getCityCode())) {
            predicates.and(
                    memberShop.cityCodeList.like("%" + qo.getCityCode() + "%")
                            .or(memberShop.cityCodeList.eq("0"))
            );
        }
        //搜索条件 - 会员状态正常
        predicates.and(memberShop.status.eq(CommonBooleanEnum.YES.getCode()));
        //查询
        JPAQuery<MemberShop> query = jpaQueryFactory.select(memberShop).from(memberShop).where(predicates);

        //总记录数
        long totalCount = query.fetchCount();

        //排序条件 - 信用积分
        if (qo.getSortCreditPoint() != null) {
            if (qo.getSortCreditPoint().equals("DESC")) {
                query.orderBy(memberShop.creditPoint.desc()).orderBy(memberShop.createTime.desc());
            }
            if (qo.getSortCreditPoint().equals("ASC")) {
                query.orderBy(memberShop.creditPoint.asc()).orderBy(memberShop.createTime.desc());
            }
        } else {
            query.orderBy(memberShop.createTime.desc());
        }

        //列表数据
        List<MemberShop> list = query.offset((long) (qo.getCurrent() - 1) * qo.getPageSize()).limit(qo.getPageSize()).fetch();
        if (CollectionUtil.isEmpty(list)) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        //调用搜索服务 -> 根据店铺ID集合获取店铺最新上架的商品
        StoreIdListRequest storeIdListRequest = new StoreIdListRequest();
        storeIdListRequest.setIdList(list.stream().map(MemberShop::getId).collect(Collectors.toList()));
        storeIdListRequest.setCount(2);
        storeIdListRequest.setShopId(shopId);
        Wrapper<Map<Long, List<CommoditySearchResponse>>> wrapper = templateFeign.getCommodityListByPublishTime(storeIdListRequest);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("请求搜索服务失败：{}", wrapper.getMessage());
        }

        //调用商品服务 -> 根据会员ID和角色ID集合获取店铺的主营分类
        Map<String, StoreResponse> map = commodityFeign.getCommodityAndCategoryByMemberIdAndMemberRoleId(
                list.stream().map(a -> {
                    MemberRequest memberRequest = new MemberRequest();
                    memberRequest.setMemberId(a.getMemberId());
                    memberRequest.setMemberRoleId(a.getRoleId());
                    return memberRequest;
                }).collect(toList())
        );

        //封装每个店铺最新上架商品、主营分类
        List<MemberShopListVO> memberShopListVOList = list.stream().map(a -> {
            MemberShopListVO vo = new MemberShopListVO();
            BeanUtils.copyProperties(a, vo);

            if (wrapper.getData() != null && CollectionUtil.isNotEmpty(wrapper.getData().get(a.getId()))) {
                vo.setProductList(
                        wrapper.getData().get(a.getId()).stream().map(product -> {
                            MemberShopListVO.ProductVO productVO = new MemberShopListVO.ProductVO();
                            BeanUtils.copyProperties(product, productVO);
                            return productVO;
                        }).collect(toList())
                );
            }
            if (CollectionUtil.isNotEmpty(map) && map.get(a.getMemberId() + "-" + a.getRoleId()) != null) {
                vo.setCustomerCategoryName(map.get(a.getMemberId() + "-" + a.getRoleId()).getCustomerCategoryName());
            }

            return vo;
        }).collect(toList());

        return Wrapper.success(new PageData<>(totalCount, memberShopListVOList));
    }

    @Override
    @ApiOperation(value = "店铺门户列表（装修）")
    public Wrapper<PageData<MemberShop>> memberShopListAdorn(PageVO dto, String memberName) {
        Pageable pageable = PageRequest.of(dto.getCurrent() - 1, dto.getPageSize(), Sort.by("createTime").descending());
        Page<MemberShop> page = StringUtils.isNotBlank(memberName) ? memberShopRepository.findAllByMemberNameContains(memberName, pageable) : memberShopRepository.findAll(pageable);
        return Wrapper.success(new PageData<>(page.getTotalElements(), page.getContent()));
    }

    @Override
    @ApiOperation(value = "店铺门户包含商品列表（装修）")
    public Wrapper<List<MemberShopInGoodsListAdornVO>> memberShopInGoodsListAdorn(MemberShopInGoodsListAdornQO qo) {
        //拿到请求参数[ {店铺ID:1, 商品ID:[1,2,3]}, 店铺ID:2, 商品ID:[4,5,6]}, {...}, {...}  ]
        List<MemberShopInGoodsListAdornQO.MemberShopInGoods> memberShopInGoodsList = qo.getMemberShopInGoodsList();
        if (CollectionUtil.isEmpty(memberShopInGoodsList)) {
            return Wrapper.success(new ArrayList<>());
        }

        //取出所有店铺ID, 根据店铺ID获取店铺, 再按照店铺ID再集合内的顺序进行排序
        List<Long> memberShopIdList = memberShopInGoodsList.stream().map(MemberShopInGoodsListAdornQO.MemberShopInGoods::getMemberShopId).collect(toList());
        //根据店铺id和区域筛选数据
        QMemberShop qMemberShop = QMemberShop.memberShop;
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(qMemberShop.id.in(memberShopIdList));
        //搜索条件 - 省编码。
        if (StringUtils.isNotBlank(qo.getProvinceCode())) {
            builder.and(
                    qMemberShop.provincesCodeList.like("%" + qo.getProvinceCode() + "%")
                            .or(qMemberShop.provincesCodeList.eq("0"))
            );
        }
        //搜索条件 - 市编码。
        if (StringUtils.isNotBlank(qo.getCityCode())) {
            builder.and(
                    qMemberShop.cityCodeList.like("%" + qo.getCityCode() + "%")
                            .or(qMemberShop.cityCodeList.eq("0"))
            );
        }
        List<MemberShop> memberShopList = jpaQueryFactory.select(qMemberShop).from(qMemberShop).where(builder).fetch();
        if (CollectionUtil.isEmpty(memberShopList)) {
            return Wrapper.success(new ArrayList<>());
        }
        memberShopList = memberShopList.stream().sorted(Comparator.comparingInt(a -> memberShopIdList.indexOf(a.getId()))).collect(toList());

        //key为店铺ID, value则是每一个店铺ID对应的商品ID
        Map<Long, List<Long>> map = new HashMap<>();
        memberShopInGoodsList.forEach(a -> {
            if (CollectionUtil.isNotEmpty(a.getGoodsId())) {
                map.put(a.getMemberShopId(), a.getGoodsId());
            }
        });

        //拿到每个店铺对应商品的ID去调用搜索服务 -> 查询商品
        List<CommoditySearchResponse> templateResponseList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(map)) {
            List<Long> goodsIdLists = map.values().stream().flatMap(Collection::stream).collect(toList());
            TemplateCommoditySearchRequest searchRequest = new TemplateCommoditySearchRequest();
            searchRequest.setCurrent(1);
            searchRequest.setPageSize(goodsIdLists.size());
            searchRequest.setShopId(qo.getShopId());
            searchRequest.setIdInList(goodsIdLists);
            Wrapper<PageData<CommoditySearchResponse>> wrapper = templateFeign.searchCommodityList(searchRequest);
            if (wrapper.getCode() == ResponseCode.SUCCESS.getCode() && CollectionUtil.isNotEmpty(wrapper.getData().getData())) {
                templateResponseList = wrapper.getData().getData();
            }
        }

        //组装
        List<CommoditySearchResponse> finalTemplateResponseList = templateResponseList;
        List<MemberShopInGoodsListAdornVO> list = memberShopList.stream().map(a -> {
            MemberShopInGoodsListAdornVO memberShopInGoodsListAdornVO = new MemberShopInGoodsListAdornVO();
            BeanUtils.copyProperties(a, memberShopInGoodsListAdornVO);

            if (CollectionUtil.isNotEmpty(finalTemplateResponseList) && CollectionUtil.isNotEmpty(map)) {
                List<Long> goodsIdList = map.get(a.getId());
                List<CommoditySearchResponse> goodsList = finalTemplateResponseList.stream().filter(b -> CollectionUtil.isNotEmpty(goodsIdList) && goodsIdList.contains(b.getId())).collect(toList());
                memberShopInGoodsListAdornVO.setGoodsVOList(
                        goodsList.stream().map(b -> {
                            MemberShopInGoodsListAdornVO.GoodsVO goods = new MemberShopInGoodsListAdornVO.GoodsVO();
                            BeanUtils.copyProperties(b, goods);
                            return goods;
                        }).collect(toList())
                );
            }
            return memberShopInGoodsListAdornVO;
        }).collect(toList());

        return Wrapper.success(list);
    }

    @Override
    @ApiOperation(value = "最新加入")
    public Wrapper<List<MemberShop>> newAddMemberShop() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 6);
        return Wrapper.success(memberShopRepository.findNewAddMemberShop(calendar.getTimeInMillis()));
    }

    @Override
    @Transactional
    @ApiOperation(value = "收藏/取消收藏")
    public Wrapper<Void> collect(CollectDTO dto, UserLoginCacheDTO user) {
        if (dto.getStatus()) {
            if (memberShopCollectRepository.existsByShopIdAndMemberIdAndUserId(dto.getId(), user.getMemberId(), user.getUserId())) {
                return Wrapper.fail("不能重复收藏，请刷新页面");
            }
            MemberShopCollect collect = new MemberShopCollect();
            collect.setShopId(dto.getId());
            collect.setMemberId(user.getMemberId());
            collect.setUserId(user.getUserId());
            memberShopCollectRepository.saveAndFlush(collect);
        } else {
            memberShopCollectRepository.deleteByShopIdAndMemberIdAndUserId(dto.getId(), user.getMemberId(), user.getUserId());
        }

        return Wrapper.success();
    }

    @Override
    @ApiOperation(value = "收藏列表")
    public Wrapper<PageData<MemberShop>> collectList(PageVO dto, UserLoginCacheDTO user) {
        //按收藏时间倒序获取当前用户收藏的店铺ID
        Pageable pageable = PageRequest.of(dto.getCurrent() - 1, dto.getPageSize(), Sort.by("createTime").descending());
        Page<MemberShopCollect> page = memberShopCollectRepository.findAllByMemberIdAndUserId(user.getMemberId(), user.getUserId(), pageable);
        List<MemberShopCollect> memberShopCollectList = page.getContent();
        if (CollectionUtil.isEmpty(memberShopCollectList)) {
            log.info("当前用户没有收藏的店铺");
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
        List<Long> memberShopIdList = memberShopCollectList.stream().map(MemberShopCollect::getShopId).collect(toList());

        //根据收藏的店铺ID获取店铺
        List<MemberShop> memberShopList = memberShopRepository.findAllByIdIn(memberShopIdList);

        //组装收藏时间
        memberShopList = memberShopList.stream().peek(a -> a.setCreateTime(
                memberShopCollectList.stream().filter(b ->
                        b.getShopId().equals(a.getId())
                ).map(MemberShopCollect::getCreateTime).findFirst().orElse(null)
        )).sorted(Comparator.comparingInt(a -> memberShopIdList.indexOf(a.getId()))).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(page.getTotalElements(), memberShopList));
    }

    @Override
    @ApiOperation(value = "根据店铺ID获取店铺")
    public Wrapper<MemberShop> findById(IdDTO dto) {
        return Wrapper.success(memberShopRepository.findById(dto.getId()).orElse(null));
    }

    @Override
    @ApiOperation(value = "根据店铺ID集合获取店铺")
    public Wrapper<List<MemberShop>> findByIdIn(IdListDTO dto) {
        return Wrapper.success(memberShopRepository.findAllById(dto.getIdList()).stream().sorted(Comparator.comparingInt(a -> dto.getIdList().indexOf(a.getId()))).collect(toList()));
    }

    @Override
    @ApiOperation(value = "根据不包含的店铺ID集合分页获取店铺")
    public Wrapper<PageData<MemberShop>> pageByIdNotIn(CommonIdListPageQO qo) {
        Pageable pageable = PageRequest.of(qo.getCurrent() - 1, qo.getPageSize(), Sort.by("createTime").descending());
        Page<MemberShop> page;
        if (CollectionUtil.isNotEmpty(qo.getIdList())) {
            page = StringUtils.isNotBlank(qo.getName()) ? memberShopRepository.findAllByIdNotInAndMemberNameContains(qo.getIdList(), qo.getName(), pageable) : memberShopRepository.findAllByIdNotIn(qo.getIdList(), pageable);
        } else {
            page = memberShopRepository.findAll(pageable);
        }
        return Wrapper.success(new PageData<>(page.getTotalElements(), page.getContent()));
    }

    @Override
    @ApiOperation(value = "根据包含的店铺ID集合分页获取店铺")
    public Wrapper<PageData<MemberShop>> pageByIdIn(CommonIdListPageQO qo) {
        Page<MemberShop> page = memberShopRepository.findAllByIdIn(qo.getIdList(), PageRequest.of(qo.getCurrent() - 1, qo.getPageSize()));
        List<MemberShop> list = page.getContent().stream().sorted(Comparator.comparingInt(a -> qo.getIdList().indexOf(a.getId()))).collect(toList());
        return Wrapper.success(new PageData<>(page.getTotalElements(), list));
    }

    @Override
    @ApiOperation(value = "根据店铺ID集合分页获取店铺【最新商品】")
    public Wrapper<PageData<MemberShopProductVO>> pageProductByIdIn(CommonIdListPageQO qo, Long shopId) {
        //根据店铺ID集合获取店铺
        Page<MemberShop> page = memberShopRepository.findAllByIdIn(qo.getIdList(), PageRequest.of(qo.getCurrent() - 1, qo.getPageSize()));
        if (CollectionUtil.isEmpty(page.getContent())) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        //调用搜索服务 -> 根据店铺ID集合获取店铺最新上架的商品
        StoreIdListRequest storeIdListRequest = new StoreIdListRequest();
        storeIdListRequest.setIdList(page.getContent().stream().map(MemberShop::getId).collect(Collectors.toList()));
        storeIdListRequest.setCount(3);
        storeIdListRequest.setShopId(shopId);
        Wrapper<Map<Long, List<CommoditySearchResponse>>> wrapper = templateFeign.getCommodityListByPublishTime(storeIdListRequest);
        if (wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("请求搜索服务失败：{}", wrapper.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_SEARCH_ERROR);
        }

        //拼装
        List<MemberShopProductVO> list = page.getContent().stream().sorted(Comparator.comparingInt(a ->
                qo.getIdList().indexOf(a.getId()))
        ).map(a -> {
            //拷贝
            MemberShopProductVO memberShopProductVO = new MemberShopProductVO();
            BeanUtils.copyProperties(a, memberShopProductVO);

            //根据店铺ID封装每个店铺最新上架商品
            if (wrapper.getData() != null && CollectionUtil.isNotEmpty(wrapper.getData().get(a.getId()))) {
                memberShopProductVO.setProductList(
                        wrapper.getData().get(a.getId()).stream().map(product -> {
                            MemberShopProductVO.ProductVO productVO = new MemberShopProductVO.ProductVO();
                            BeanUtils.copyProperties(product, productVO);
                            return productVO;
                        }).collect(Collectors.toList())
                );
            }
            return memberShopProductVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(page.getTotalElements(), list));
    }

    @Override
    @ApiOperation(value = "根据店铺ID集合获取店铺【主营分类】")
    public Wrapper<List<MemberShopMainCategoryVO>> findMainCategoryByIdIn(IdListDTO dto) {
        //根据店铺ID集合获取店铺
        List<MemberShop> memberShopList = memberShopRepository.findAllById(dto.getIdList());
        if (CollectionUtil.isEmpty(memberShopList)) {
            return Wrapper.success(new ArrayList<>());
        }

        //调用商品服务 -> 根据会员ID和角色ID集合获取店铺的主营分类
        Map<String, StoreResponse> map = commodityFeign.getCommodityAndCategoryByMemberIdAndMemberRoleId(
                memberShopList.stream().map(a -> {
                    MemberRequest memberRequest = new MemberRequest();
                    memberRequest.setMemberId(a.getMemberId());
                    memberRequest.setMemberRoleId(a.getRoleId());
                    return memberRequest;
                }).collect(toList())
        );

        //封装主营分类并且返回
        return Wrapper.success(
                memberShopList.stream().sorted(Comparator.comparingInt(a ->
                        dto.getIdList().indexOf(a.getId())
                )).map(a -> {
                    MemberShopMainCategoryVO memberShopMainCategoryVO = new MemberShopMainCategoryVO();
                    BeanUtils.copyProperties(a, memberShopMainCategoryVO);
                    if (CollectionUtil.isNotEmpty(map) && map.get(a.getMemberId() + "-" + a.getRoleId()) != null) {
                        memberShopMainCategoryVO.setMainCategory(map.get(a.getMemberId() + "-" + a.getRoleId()).getCustomerCategoryName());
                    }
                    return memberShopMainCategoryVO;
                }).collect(toList())
        );
    }
}
